#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>

#define PORT 8888
#define IP "192.168.47.165"

/*
建立套接字 socket 返回 socketfd
int socket(int domain, int type, int protocol);
    domain 网络协议 AF_INET   AF_INET6
    type   SOCK_STREAM  选择TCP协议 SOCK_DGRAM  选择UDP

绑定自己的IP和端口号
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    sockfd  套接字
    addr    结构体sockaddr的指针 ip 和端口号
    addrlen 结构体大小

listen() 声明sockfd处于监听状态
int listen(int sockfd, int backlog);
    sockfd  套接字
    backlog 同时最多支持连接上来的客户端总数

等待接受客户端连接 返回已连接的套接字文件描述符
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    sockfd  套接字
    addr    结构体sockaddr的指针 ip 和端口号
    addrlen 结构体大小

接收数据居失败-1返回0表示客户端断开连接
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    sockfd：已连接的套接字文件描述符connectfd
    buf：   接收到的数据存储到这里
    len:    接收数据的大小
    flagS:  一般设置为0

*/

int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 0 表示使用默认协议
    if (sockfd < 0)
    {
        perror("socket error");
        return -1;
    }

    // 创建地址结构体
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));

    addr.sin_family = AF_INET;            // 使用IPv4
    addr.sin_port = htons(PORT);          // 端口号 8888
    addr.sin_addr.s_addr = inet_addr(IP); // inet_addr 将点分十进制IP地址转换为网络字节序

    // 绑定
    bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));

    // 监听
    listen(sockfd, 10); // 10 表示最大连接数
    printf("监听中...\n");

    pthread_t tid[10];
    int i = 0;

    while (1)
    {
        printf("waiting....\n");

        struct sockaddr_in client_addr;
        memset(&client_addr, 0, sizeof(client_addr));

        // 等待客户端连接
        int ClientAddr_len = sizeof(client_addr);
        int connfd = accept(sockfd, (struct sockaddr *)&client_addr, &ClientAddr_len);
        if (connfd < 0)
        {
            perror("accept");
            continue;
        }
        printf("Client ip:%s, port:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        while (1)
        {
            // 接收数据
            char buf[1024];
            ssize_t recv_res = recv(connfd, buf, sizeof(buf), 0);
            if (recv_res < 0)
            {
                perror("recv");
                continue;
            }
            if (recv_res == 0)
            {
                printf("客户端断开连接\n");
                close(connfd);
                break;
            }
            printf("客户端发送的数据：%s\n", buf);
        }

        close(connfd);
        printf("客户端断开连接\n");
    }

    return 0;
}